/*
 * CgExpression.c
 *
 *  Created on: 2012/06/07
 *      Author: guanxiaoying
 */
#include "../coredef.h"
#include "../cc/cc.h"
#include "cg.h"

static CG_RESULT cg_Expression( AST astExp, BOOL bSideEffect );


static AST cg_GetStUnMemberOffset( AST astExp, AST astSym ){
	PSZ pszSymName = stSymbolInfoAccess.name.get( astSym );
	PSZ pszVariName;
	AST astType;
	AST astMemSym=0;
	AST astUnitChain;

	astType = stExpressionAccess.castedType.get( astExp );
	astUnitChain = stTypeInfoAccess.memChain.get( astType );
	while( astUnitChain ){
		astMemSym = stUniteChainAccess.parameter_sym.get( astUnitChain );
		pszVariName = stSymbolInfoAccess.name.get( astMemSym );
		if( 0 == strcmp( pszVariName, pszSymName )){
			break;
		}
		astUnitChain = stUniteChainAccess.next.get( astUnitChain );
	}
	if( astMemSym != 0 ){
		return stSymbolInfoAccess.memOffset.get( astMemSym );
	}
	return 0;
}
static CG_RESULT cg_ExpPullPostIncDec( BOOL bClear ){
	AST astMax = stPostIncDecStkAccess.getMax();
	AST astCnt = MIN_ARRAY;
	AST astCmdList;
	CG_RESULT result={0,0};

	TRY;
	while( astCnt <= astMax ){
		astCmdList = CG_NewCmdListByKind( stPostIncDecStkAccess.kind.get(astCnt),
				stPostIncDecStkAccess.expr.get( astCnt ) );
		stCmdListAccess.leftOperand.set( astCmdList, stPostIncDecStkAccess.operand.get( astCnt ));
		CG_CmdListSetType( astCmdList,
				stExpressionAccess.castedType.get( stPostIncDecStkAccess.expr.get( astCnt ) ) );
		result = CG_MergeCmdList( result, astCmdList );
		astCnt++;
	}
	if( bClear ){
		stPostIncDecStkAccess.clear();
	}
	CATCH(result);
	return result;
}
static U4 cg_GetCmdListKind( AST astExp ){
	U4 kind;
	kind = stExpressionAccess.opKind.get( astExp );
	switch( kind ){
	case EXPR_PLUS   :
		return 0;
	case EXPR_MINUS  :
		return ASM_CMD_MINUS;
	case EXPR_NEGATION   :
		return ASM_CMD_NEGATION;
	case EXPR_BIT_NEGATION  :
		return ASM_CMD_BITNEGATION;
	case EXPR_CAST :
		return ASM_CMD_CAST;
	case EXPR_MUL  :
		return ASM_CMD_MUL;
	case EXPR_DIV  :
		return ASM_CMD_DIV;
	case EXPR_MOD  :
		return ASM_CMD_MOD;
	case EXPR_ADD   :
		return ASM_CMD_ADD;
	case EXPR_SUB   :
		return ASM_CMD_SUB;
	case EXPR_LEFTSHIFT :
		return ASM_CMD_LSFT;
	case EXPR_RIGHTSHIFT:
		return ASM_CMD_RSFT;
	case EXPR_GREATER  :
		return ASM_CMD_GREATER;
	case EXPR_GREATEREQU   :
		return ASM_CMD_GREATEREQUAL;
	case EXPR_LESS  :
		return ASM_CMD_LESS;
	case EXPR_LESSEQU   :
		return ASM_CMD_LESSEQUAL;
	case EXPR_EQUAL :
		return ASM_CMD_EQUAL;
	case EXPR_UNEQUAL   :
		return ASM_CMD_UNEQUAL;
	case EXPR_BIT_AND   :
		return ASM_CMD_BITAND;
	case EXPR_BIT_EXOR  :
		return ASM_CMD_BITEXOR;
	case EXPR_BIT_INOR  :
		return ASM_CMD_BITINOR;
	case EXPR_LOGIC_AND :
		return ASM_CMD_LGAND;
	case EXPR_LOGIC_OR  :
		return ASM_CMD_LGOR;
	case EXPR_CONDITION :
		return ASM_CMD_BRANCH;
	case EXPR_ASSIGN:
		return ASM_CMD_ASSIGN;
	}
	return 0;
}
static AST cg_ExpOperandIdentifier( AST astExp ){
	AST astOperand=0;
	AST astSym;
	AST astVari;
//	BOOL bFindResult;

	TRY;
	astSym = stExpressionAccess.result_symbol.get( astExp );
	if( stSymbolInfoAccess.kind.get( astSym ) == SYMBOL_KIND_FUNCTION ){
		astVari = CG_ConvertToFunction( astSym );
		astOperand = CG_NewFunctionOperand( astVari );
	}else{
		if( stSymbolInfoAccess.linkage.get( astSym ) > 0 ){
			astVari = CG_ConvertToVariable( astSym );
		}else{
			astVari = CG_ConvertToTemporaryVariable( astSym );
		}
		astOperand = CG_NewVariableOperand( astVari );
	}
	CATCH(0);
	return astOperand;
}
static AST cg_ExpOperandConstant( AST astExp ){
	AST astOperand;
	AST astConstant;
	TRY;
	astConstant = stExpressionAccess.result_value.get( astExp );
	astOperand = CG_NewConstantOperand( astConstant );
	CATCH(0);
	return astOperand;
}
static AST cg_ExpOperandConstString( AST astExp ){
	AST astOperand;
	AST astConstantStr;
	TRY;
	astConstantStr = stExpressionAccess.result_constStr.get( astExp );
	astOperand = CG_NewConstantStringOperand( astConstantStr );
	CATCH(0);
	return astOperand;
}
static CG_RESULT cg_ExpSolvePrimary( AST astExp, BOOL bSideEffect ){
	AST astOperand;
	U4  opKind;
	AST astCmdList;
	CG_RESULT result = { 0, 0 };
	TRY;
	if( bSideEffect ){
		opKind = stExpressionAccess.opKind.get( astExp );
		if( opKind == EXPR_IDENTIFIER
				|| opKind == EXPR_CONSTANT
				|| opKind == EXPR_STRING ){
			astCmdList = CG_NewCmdListByKind( ASM_CMD_GETOPERAND, astExp );
			if( opKind == EXPR_IDENTIFIER ){
				astOperand = cg_ExpOperandIdentifier( astExp );
			}else if( opKind == EXPR_CONSTANT ){
				astOperand = cg_ExpOperandConstant( astExp );
			}else{
				astOperand = cg_ExpOperandConstString( astExp );
			}
			stCmdListAccess.leftOperand.set( astCmdList, astOperand );
			CG_CmdListSetType( astCmdList, stExpressionAccess.type.get( astExp ));
			result = CG_MergeCmdList( result, astCmdList );
		}
	}
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolveStatement( AST astExp, BOOL bSideEffect ){
	AST astStmt;
	CG_RESULT result = { 0, 0 };
	TRY;
	astStmt = stExpressionAccess.result_statement.get( astExp );
	result = CG_Statement( astStmt, bSideEffect );
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolveArray( AST astExp, BOOL bSideEffect ){
	AST astLeftExp;
	AST astRightExp;
	AST astConstant;
	AST astCmdList;
	AST astOperandLeft;
	AST astOperandRight;
	AST astVari;
	CG_RESULT result = { 0, 0 };
	CG_RESULT result_child = { 0, 0 };
	TRY;
	astRightExp = stExpressionAccess.rightChild.get( astExp );
	astConstant = stExpressionAccess.constValue.get( astRightExp );
	if( astConstant != 0 ){
		astLeftExp = stExpressionAccess.leftChild.get( astExp );
		result = cg_Expression( astLeftExp, bSideEffect );
		if( bSideEffect ){
			if( stCmdListAccess.opKind.get( result.astBegin ) == ASM_CMD_GETOPERAND ){
				astOperandLeft = stCmdListAccess.leftOperand.get( result.astBegin );
				if( stOperandAccess.kind.get( astOperandLeft ) == OPERAND_OBJECT ){
					astVari = stOperandAccess.parameter.get( astOperandLeft );
					astVari = CG_GetArrayMember( astVari, astConstant );
					if( astVari > 0 ){
						CG_CmdListSetType( result.astBegin, stExpressionAccess.type.get( astExp ) );
						stOperandAccess.parameter.set( astOperandLeft, astVari );
						return result;
					}
				}
			}
			astCmdList = CG_NewCmdListByKind( ASM_CMD_GETOFFSET_UNIT, astExp );
			astOperandLeft = CG_NewResultOperand( result.astEnd );
			stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
			CG_CmdListSetType( astCmdList, stExpressionAccess.castedType.get( astLeftExp ) );
			astOperandRight = CG_NewConstantOperand( astConstant );
			stCmdListAccess.rightOperand.set( astCmdList, astOperandRight );
			result = CG_MergeCmdList( result, astCmdList );

			astCmdList = CG_NewCmdListByKind( ASM_CMD_GETMEMDATA, astExp );
			astOperandLeft = CG_NewResultOperand( result.astEnd );
			stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
			CG_CmdListSetType( astCmdList, stExpressionAccess.type.get( astExp ));
			result = CG_MergeCmdList( result, astCmdList );
		}
		/*
		 * else  astRetCmdList = 0;
		 */
	}else{
		if( bSideEffect ){
			astLeftExp = stExpressionAccess.leftChild.get( astExp );
			result = cg_Expression( astLeftExp, TRUE );
			astOperandLeft = CG_NewResultOperand( result.astEnd );

			result_child = cg_Expression( astRightExp, TRUE );
			result = CG_MergeResult( result, result_child );

			astOperandRight = CG_NewResultOperand( result_child.astEnd );
			astCmdList = CG_NewCmdListByKind( ASM_CMD_GETOFFSET_UNIT, astExp );

			stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
			stCmdListAccess.rightOperand.set( astCmdList, astOperandRight );
			CG_CmdListSetType( astCmdList, stExpressionAccess.castedType.get( astLeftExp ) );
			result = CG_MergeCmdList( result, astCmdList );

			astCmdList = CG_NewCmdListByKind( ASM_CMD_GETMEMDATA, astExp );
			astOperandLeft = CG_NewResultOperand( result.astEnd );
			stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
			CG_CmdListSetType( astCmdList, stExpressionAccess.type.get( astExp ) );
			result = CG_MergeCmdList( result, astCmdList );
		}else{
			astLeftExp = stExpressionAccess.leftChild.get( astExp );
			result = cg_Expression( astLeftExp, FALSE );

			result_child = cg_Expression( astRightExp, FALSE );
			result = CG_MergeResult( result, result_child );
		}
		/*
		 * else  astRetCmdList = 0;
		 */
	}
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolveFuncCall( AST astExp, BOOL bSideEffect ){
	AST astLeftExp;
	AST astRightExp;
	AST astPreCmdList;
	AST astCmdList;
	AST astOperandLeft;
	AST astOperandRight;
	U4 kind;
	CG_RESULT result = { 0, 0 };
	CG_RESULT result_child = { 0, 0 };
	TRY;
	astLeftExp = stExpressionAccess.leftChild.get( astExp );
	if( stExpressionAccess.opKind.get( astLeftExp ) == EXPR_IDENTIFIER ){
		astOperandLeft = cg_ExpOperandIdentifier( astLeftExp );
	}else{
		result = cg_Expression( astLeftExp, TRUE );
		astOperandLeft = CG_NewResultOperand( result.astEnd );
	}

	astRightExp = stExpressionAccess.rightChild.get( astExp );
	if( astRightExp > 0 ){
		astPreCmdList = stCmdListAccess.getMax()+1;
		result_child = cg_Expression( astRightExp, TRUE );
		result = CG_MergeResult( result, result_child );
		kind = stExpressionAccess.opKind.get( astRightExp );
		if( kind != EXPR_ARG ){
			if( result.astBegin > 0 ){
				astOperandRight = CG_NewResultOperand( result_child.astEnd );
				astCmdList = CG_NewCmdListByKind( ASM_CMD_ASSIGNARG, astRightExp );
				stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft  );
				stCmdListAccess.rightOperand.set( astCmdList, astOperandRight );
				CG_CmdListSetType( astCmdList, stExpressionAccess.castedType.get( astRightExp ) );
				result = CG_MergeCmdList( result, astCmdList );
			}
		}else{
			astCmdList = stCmdListAccess.getMax();
			while( astPreCmdList <= astCmdList  ){
				if( stCmdListAccess.opKind.get( astCmdList ) == ASM_CMD_ASSIGNARG ){
					if( stCmdListAccess.leftOperand.get( astCmdList ) == 0 ){
						stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
					}
				}
				astPreCmdList++;
			}
		}
		result_child = cg_ExpPullPostIncDec(TRUE);
		result = CG_MergeResult( result, result_child );
	}

	astCmdList = CG_NewCmdListByKind( ASM_CMD_CALL, astExp );
	stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
	CG_CmdListSetType( astCmdList, stExpressionAccess.type.get( astExp ) );
	result = CG_MergeCmdList( result, astCmdList );
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolveMember( AST astExp, BOOL bSideEffect ){
	AST astLeftExp;
	AST astRightExp;
	AST astSym;
	AST astConstant;
	AST astCmdListOffset;
	AST astOperandLeft;
	AST astOperandRight;
	AST astVari;
	S4  offset;
	CG_RESULT result = { 0, 0 };
	CG_RESULT result_child = { 0, 0 };
	TRY;
	astLeftExp = stExpressionAccess.leftChild.get( astExp );
	astRightExp = stExpressionAccess.rightChild.get( astExp );
	astSym = stExpressionAccess.result_symbol.get( astRightExp );
	result_child = cg_Expression( astLeftExp, bSideEffect );
	if( bSideEffect ){
		if( stCmdListAccess.opKind.get( result_child.astBegin ) == ASM_CMD_GETOPERAND ){
			astOperandLeft = stCmdListAccess.leftOperand.get( result_child.astBegin  );
			if( stOperandAccess.kind.get( astOperandLeft ) == OPERAND_OBJECT ){
				astVari = stOperandAccess.parameter.get( astOperandLeft );
				astVari = CG_GetStUnMember( astVari, astSym );
				if( astVari != 0 ){
					stOperandAccess.parameter.set( astOperandLeft, astVari );
					CG_CmdListSetType( result_child.astBegin, stExpressionAccess.type.get( astExp ));
					result = result_child;
				}
			}
		}
		if( result.astBegin == 0 ){
			VARVALUE value={0};
			astOperandLeft = CG_NewResultOperand( result_child.astEnd );
			astCmdListOffset = CG_NewCmdListByKind( ASM_CMD_GETOFFSET, astExp );
			offset = cg_GetStUnMemberOffset( astLeftExp, astSym );
			value.u8Remainder = offset;
			value.u4Quotient = 0;
			value.sign = 1;
			value.overflow = 0;
			astConstant = CcValueAddVarValue( CcTypeGetBasicType( "int", 0 ), value );
			astOperandRight = CG_NewConstantOperand( astConstant );
			stCmdListAccess.leftOperand.set( astCmdListOffset, astOperandLeft );
			stCmdListAccess.rightOperand.set( astCmdListOffset, astOperandRight );
			CG_CmdListSetType( result_child.astBegin, stExpressionAccess.type.get( astExp ));
			result = CG_MergeCmdList( result_child, astCmdListOffset );
		}
	}else{
		result = result_child;
	}
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolvePtrMember( AST astExp, BOOL bSideEffect ){
	AST astLeftExp;
//	AST astRightExp;
	AST astSym;
	AST astConstant;
	AST astCmdList;
	AST astOperandLeft;
	AST astOperandRight;
	S4  offset;
	AST astType;
	VARVALUE value={0};
	CG_RESULT result = { 0, 0 };
	CG_RESULT result_child = { 0, 0 };
	TRY;
	astLeftExp = stExpressionAccess.leftChild.get( astExp );
//	astRightExp = stExpressionAccess.rightChild.get( astExp );
	astSym = stExpressionAccess.result_symbol.get( astExp );
	result_child = cg_Expression( astLeftExp, bSideEffect );
	if( bSideEffect ){
		astOperandLeft = CG_NewResultOperand( result_child.astEnd );
		astCmdList = CG_NewCmdListByKind( ASM_CMD_GETMEMDATA, astLeftExp );
		stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
		astType = stExpressionAccess.type.get( astLeftExp );
		astType = stTypeInfoAccess.elementType.get( astType );
		CG_CmdListSetType( astCmdList, astType );
		result = CG_MergeCmdList( result_child, astCmdList );

		astCmdList = CG_NewCmdListByKind( ASM_CMD_GETOFFSET, astExp );
		offset = cg_GetStUnMemberOffset( astLeftExp, astSym );
		value.u8Remainder = offset;
		value.u4Quotient = 0;
		value.sign = 1;
		value.overflow = 0;
		astConstant = CcValueAddVarValue( CcTypeGetBasicType( "int", 0 ), value );
		astOperandRight = CG_NewConstantOperand( astConstant );
		stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
		stCmdListAccess.rightOperand.set( astCmdList, astOperandRight );
		CG_CmdListSetType( astCmdList, stExpressionAccess.type.get( astExp ) );
		result = CG_MergeCmdList( result, astCmdList );
	}else{
		result = result_child;
	}
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolvePostIncDec( AST astExp, BOOL bSideEffect ){
	AST astLeftExp;
	AST astOperandLeft;
	AST astStack;
	CG_RESULT result = { 0, 0 };
	TRY;
	astLeftExp = stExpressionAccess.leftChild.get( astExp );
	result = cg_Expression( astLeftExp, TRUE );
	if( stCmdListAccess.opKind.get( result.astBegin ) == ASM_CMD_GETOPERAND ){
		astOperandLeft = stCmdListAccess.leftOperand.get( result.astBegin );
	}else{
		astOperandLeft = CG_NewResultOperand( result.astEnd );
	}
	stPostIncDecStkAccess.alloc(1);
	astStack = stPostIncDecStkAccess.getMax();
	if( stExpressionAccess.opKind.get( astExp ) == EXPR_POSTINC ){
		stPostIncDecStkAccess.kind.set( astStack, ASM_CMD_INC );
	}else{
		stPostIncDecStkAccess.kind.set( astStack, ASM_CMD_DEC );
	}
	stPostIncDecStkAccess.operand.set( astStack, astOperandLeft );
	stPostIncDecStkAccess.expr.set( astStack, astExp );
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolveCompoundLiterals( AST astExp, BOOL bSideEffect ){
	AST astVari;
	AST astChildExp;
	AST astDeclaration;
	AST astCmdList;
	AST astOperand;
	CG_RESULT result = { 0, 0 };
	CG_RESULT result_child = { 0, 0 };
	TRY;
	astVari = CG_ConvertToTempVari_CompoundLiterals( astExp );
	astChildExp = stExpressionAccess.leftChild.get( astExp );
	astDeclaration = stExpressionAccess.result_declaration.get( astChildExp );
	result = CG_Declaration( astDeclaration );
	astChildExp = stExpressionAccess.rightChild.get( astExp );
	result_child = CG_AssignInitializerToVariable( astVari,
			stExpressionAccess.result_exprlist.get( astChildExp ), TRUE );
	result = CG_MergeResult( result, result_child );
	astCmdList = CG_NewCmdListByKind( ASM_CMD_GETOPERAND, astExp );
	astOperand = CG_NewVariableOperand( astVari );
	stCmdListAccess.leftOperand.set( astCmdList, astOperand );
	CG_CmdListSetType( astCmdList, stExpressionAccess.type.get( astExp ) );
	result = CG_MergeCmdList( result, astCmdList );
	CATCH( result );
	return result;
}
static CG_RESULT cg_ExpSolvePreIncDec( AST astExp, BOOL bSideEffect ){
	AST astLeftExp;
	AST astCmdList;
	AST astOperandLeft;
	CG_RESULT result = { 0, 0 };
	TRY;
	astLeftExp = stExpressionAccess.leftChild.get( astExp );
	result = cg_Expression( astLeftExp, bSideEffect );
	if( stCmdListAccess.opKind.get( result.astBegin ) == ASM_CMD_GETOPERAND ){
		if( stExpressionAccess.opKind.get( astExp ) == EXPR_PREINC ){
			stCmdListAccess.opKind.set( result.astBegin, ASM_CMD_INC );
		}else{
			stCmdListAccess.opKind.set( result.astBegin, ASM_CMD_DEC );
		}
	}else{
		astOperandLeft = CG_NewResultOperand( result.astEnd );
		if( stExpressionAccess.opKind.get( astExp ) == EXPR_PREINC ){
			astCmdList = CG_NewCmdListByKind( ASM_CMD_INC, astExp );
		}else{
			astCmdList = CG_NewCmdListByKind( ASM_CMD_DEC, astExp );
		}
		stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
		CG_CmdListSetType( astCmdList, stExpressionAccess.castedType.get( astExp ) );
		result = CG_MergeCmdList( result, astCmdList );
	}
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolveAddress( AST astExp, BOOL bSideEffect ){
	AST astLeftExp;
	AST astCmdList;
	AST astOperandLeft;
	CG_RESULT result = { 0, 0 };
	TRY;
	astLeftExp = stExpressionAccess.leftChild.get( astExp );
	result = cg_Expression( astLeftExp, bSideEffect );
	if( bSideEffect ){
		astOperandLeft = CG_NewResultOperand( result.astBegin );
		astCmdList = CG_NewCmdListByKind( ASM_CMD_GETADDR, astExp );
		stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
		CG_CmdListSetType( astCmdList, stExpressionAccess.type.get( astExp ));
		result = CG_MergeCmdList( result, astCmdList );
	}
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolveAsterisk( AST astExp, BOOL bSideEffect ){
	AST astLeftExp;
	AST astCmdList;
	AST astOperandLeft;
	CG_RESULT result = { 0, 0 };
	TRY;
	astLeftExp = stExpressionAccess.leftChild.get( astExp );
	result = cg_Expression( astLeftExp, bSideEffect );
	if( bSideEffect ){
		astOperandLeft = CG_NewResultOperand( result.astEnd );
		astCmdList = CG_NewCmdListByKind( ASM_CMD_GETMEMDATA, astExp );
		stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
		CG_CmdListSetType( astCmdList, stExpressionAccess.type.get( astExp ));
		result = CG_MergeCmdList( result, astCmdList );
	}
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolveSingleOp( AST astExp, BOOL bSideEffect ){
	AST astLeftExp;
	AST astCmdList;
	AST astOperandLeft;
	CG_RESULT result = { 0, 0 };
	U4 kind = cg_GetCmdListKind( astExp );
	TRY;
	astLeftExp = stExpressionAccess.leftChild.get( astExp );
	result = cg_Expression( astLeftExp, bSideEffect );
	if( bSideEffect && kind > 0 ){
		astOperandLeft = CG_NewResultOperand( result.astEnd );
		astCmdList = CG_NewCmdListByKind( kind, astExp );
		stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
		CG_CmdListSetType( astCmdList, stExpressionAccess.type.get( astExp ));
		result = CG_MergeCmdList( result, astCmdList );
	}
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolveSizeof( AST astExp, BOOL bSideEffect ){
	AST astOperand;
	AST astCmdList=0;
	CG_RESULT result = { 0, 0 };
	TRY;
	if( bSideEffect ){
		result.astBegin = CG_NewCmdListByKind( ASM_CMD_GETOPERAND, astExp );
		astOperand = cg_ExpOperandConstant( astExp );
		stCmdListAccess.leftOperand.set( astCmdList, astOperand );
		CG_CmdListSetType( astCmdList, stExpressionAccess.type.get( astExp ));
		result.astEnd = result.astBegin;
	}
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolveCast( AST astExp, BOOL bSideEffect ){
	AST astCmdList;
	AST astLeftExp;
	AST astOperandLeft;
	CG_RESULT result = { 0, 0 };
	CG_RESULT result_child = { 0, 0 };
	TRY;
	astLeftExp = stExpressionAccess.leftChild.get( astExp );
	result = cg_Expression( astLeftExp, bSideEffect );
	astLeftExp = stExpressionAccess.rightChild.get( astExp );
	result_child = cg_Expression( astLeftExp, bSideEffect );
	result = CG_MergeResult( result, result_child );
	if( bSideEffect ){
		astOperandLeft = CG_NewResultOperand( result_child.astEnd );
		astCmdList = CG_NewCmdListByKind( ASM_CMD_CAST, astExp );
		stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
		CG_CmdListSetType( astCmdList, stExpressionAccess.type.get( astExp ));
		result = CG_MergeCmdList( result, astCmdList );
	}
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolveBinary( AST astExp, BOOL bSideEffect ){
	AST astLeftExp;
	AST astRightExp;
	AST astCmdList;
	AST astOperandLeft;
	AST astOperandRight;
	U4 kind;
	CG_RESULT result = { 0, 0 };
	CG_RESULT result_child = { 0, 0 };
	TRY;
	if( bSideEffect ){
		kind = cg_GetCmdListKind( astExp);
		astLeftExp = stExpressionAccess.leftChild.get( astExp );
		result = cg_Expression( astLeftExp, bSideEffect );
		astOperandLeft = CG_NewResultOperand( result.astEnd );

		astRightExp = stExpressionAccess.rightChild.get( astExp );
		result_child = cg_Expression( astRightExp, bSideEffect );
		result = CG_MergeResult( result, result_child );
		astOperandRight = CG_NewResultOperand( result_child.astEnd );

		astCmdList = CG_NewCmdListByKind( kind, astExp );
		stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
		stCmdListAccess.rightOperand.set( astCmdList, astOperandRight );
		CG_CmdListSetType( astCmdList, stExpressionAccess.type.get( astExp ));
		result = CG_MergeCmdList( result, astCmdList );
	}else{
		astLeftExp = stExpressionAccess.leftChild.get( astExp );
		astRightExp = stExpressionAccess.rightChild.get( astExp );
		result = cg_Expression( astLeftExp, bSideEffect );
		result_child = cg_Expression( astRightExp, bSideEffect );
		result = CG_MergeResult( result, result_child );
	}
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolveBinaryWithSqPoint( AST astExp, BOOL bSideEffect ){
	AST astLeftExp;
	AST astRightExp;
	AST astCmdList;
	AST astOperandLeft;
	AST astOperandRight;
	U4 kind;
	CG_RESULT result = { 0, 0 };
	CG_RESULT result_child = { 0, 0 };
	TRY;


	kind = cg_GetCmdListKind( astExp );
	astLeftExp = stExpressionAccess.leftChild.get( astExp );
	result = cg_Expression( astLeftExp, bSideEffect );
	if( bSideEffect ){
		astOperandLeft = CG_NewResultOperand( result.astEnd );
	}
	result_child = cg_ExpPullPostIncDec(TRUE);
	result = CG_MergeResult( result, result_child );

	astRightExp = stExpressionAccess.rightChild.get( astExp );
	result_child = cg_Expression( astRightExp, bSideEffect );
	result = CG_MergeResult( result, result_child );
	if( bSideEffect ){
		astOperandRight = CG_NewResultOperand( result_child.astEnd );
		astCmdList = CG_NewCmdListByKind( kind, astExp );
		stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
		stCmdListAccess.rightOperand.set( astCmdList, astOperandRight );
		CG_CmdListSetType( astCmdList, stExpressionAccess.type.get( astExp ));
		result = CG_MergeCmdList( result, astCmdList );
	}
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolveTernary( AST astExp, BOOL bSideEffect ){
	AST astLeftExp;
	AST astRightExp;
	AST astCmdList;
	AST astOperand;
	AST astBrCmdList;
	AST astBrCmdListEnd;
	AST astType;
	CG_RESULT result = { 0, 0 };
	CG_RESULT result_body = { 0, 0 };
	CG_RESULT result_child = { 0, 0 };
	TRY;
	astLeftExp = stExpressionAccess.leftChild.get( astExp );
	result = cg_Expression( astLeftExp, TRUE );

	astOperand = CG_NewResultOperand( result.astEnd );
	astCmdList = CG_NewJudgeCmdList( astLeftExp );

	result = CG_MergeCmdList( result, astCmdList );
	stCmdListAccess.leftOperand.set( astCmdList, astOperand );


	astBrCmdList = CG_NewChooseCmdList( astLeftExp );
	astBrCmdListEnd = CG_NewChooseEndCmdList( astLeftExp );
//	astOperand = CG_NewResultOperand( astBrCmdListEnd );
//	stCmdListAccess.outputOperand.set( astBrCmdList, astOperand );
	result = CG_MergeCmdList( result, astBrCmdList );


	astRightExp = stExpressionAccess.rightChild.get( astExp );
	astType = stExpressionAccess.type.get( astRightExp );
	CG_CmdListSetType( astBrCmdListEnd, astType );
	astLeftExp = stExpressionAccess.leftChild.get( astRightExp );
	astRightExp = stExpressionAccess.rightChild.get( astRightExp );

	result_child = cg_ExpPullPostIncDec(FALSE);
	result_body = cg_Expression( astLeftExp, TRUE );
	result_child = CG_MergeResult( result_child, result_body );

	astOperand = CG_NewResultOperand( result_child.astBegin );
	stCmdListAccess.leftOperand.set( astBrCmdList, astOperand );
	astOperand = CG_NewResultOperand( result_child.astEnd );
	stCmdListAccess.leftOperand.set( astBrCmdListEnd, astOperand );
	result_child = CG_MergeCmdList( result_child, astBrCmdListEnd );

	result_child = cg_ExpPullPostIncDec(TRUE);
	result_body = cg_Expression( astRightExp, TRUE );
	result_child = CG_MergeResult( result_child, result_body );

	astOperand = CG_NewResultOperand( result_child.astBegin );
	stCmdListAccess.rightOperand.set( astBrCmdList, astOperand );
	astOperand = CG_NewResultOperand( result_child.astEnd );
	stCmdListAccess.rightOperand.set( astBrCmdListEnd, astOperand );
	result_child = CG_MergeCmdList( result_child, astBrCmdListEnd );

	result = CG_MergeCmdList( result, astBrCmdListEnd );
//	result.astEnd = astBrCmdListEnd;
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolveAssign( AST astExp, BOOL bSideEffect ){
	AST astLeftExp;
	AST astRightExp;
	AST astCmdList;
	AST astOperandLeft;
	AST astOperandRight;
	U4 kind;
	CG_RESULT result = { 0, 0 };
	CG_RESULT result_child = { 0, 0 };
	TRY;
	kind = stExpressionAccess.opKind.get( astExp );
	switch( kind ){
	case EXPR_ASSIGN:
		kind = 0;
		break;
	case EXPR_MUL_ASSIGN:
		kind = ASM_CMD_MUL;
		break;
	case EXPR_DIV_ASSIGN:
		kind = ASM_CMD_DIV;
		break;
	case EXPR_MOD_ASSIGN:
		kind = ASM_CMD_MOD;
		break;
	case EXPR_ADD_ASSIGN:
		kind = ASM_CMD_ADD;
		break;
	case EXPR_SUB_ASSIGN:
		kind = ASM_CMD_SUB;
		break;
	case EXPR_LSHT_ASSIGN   :
		kind = ASM_CMD_LSFT;
		break;
	case EXPR_RSHT_ASSIGN   :
		kind = ASM_CMD_RSFT;
		break;
	case EXPR_BITAND_ASSIGN :
		kind = ASM_CMD_BITAND;
		break;
	case EXPR_BITEXOR_ASSIGN :
		kind = ASM_CMD_BITEXOR;
		break;
	case EXPR_BITINOR_ASSIGN :
		kind = ASM_CMD_BITINOR;
		break;
	default:
		kind = 0;
		break;
	}

	astLeftExp = stExpressionAccess.leftChild.get( astExp );
	astRightExp = stExpressionAccess.rightChild.get( astExp );
	result = cg_Expression( astLeftExp, TRUE );
	astOperandLeft = CG_NewResultOperand( result.astEnd );
	result_child = cg_Expression( astRightExp, TRUE );
	result = CG_MergeResult( result, result_child );
	if( kind != 0 ){
		astOperandRight = CG_NewResultOperand( result_child.astEnd );
		astCmdList = CG_NewCmdListByKind( kind, astExp );
		stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
		stCmdListAccess.rightOperand.set( astCmdList, astOperandRight );
		CG_CmdListSetType( astCmdList, stExpressionAccess.castedType.get( astRightExp ) );
		result = CG_MergeCmdList( result, astCmdList );
		astOperandRight = CG_NewResultOperand( result.astEnd );
	}else{
		astOperandRight = CG_NewResultOperand( result_child.astEnd );
	}

	astCmdList = CG_NewCmdListByKind( ASM_CMD_ASSIGN, astExp );
	stCmdListAccess.leftOperand.set( astCmdList, astOperandLeft );
	stCmdListAccess.rightOperand.set( astCmdList, astOperandRight );
	CG_CmdListSetType( astCmdList, stExpressionAccess.castedType.get( astLeftExp ) );
	result = CG_MergeCmdList( result, astCmdList );
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolveComma( AST astExp, BOOL bSideEffect ){
	AST astLeftExp;
	AST astRightExp;
	CG_RESULT result = { 0, 0 };
	CG_RESULT result_child = { 0, 0 };
	TRY;

	astLeftExp = stExpressionAccess.leftChild.get( astExp );
	result = cg_Expression( astLeftExp, bSideEffect );
	result_child = cg_ExpPullPostIncDec(TRUE);
	result = CG_MergeResult( result, result_child );

	astRightExp = stExpressionAccess.rightChild.get( astExp );
	result_child = cg_Expression( astRightExp, TRUE );
	result = CG_MergeResult( result, result_child );
	CATCH(result);
	return result;
}
static CG_RESULT cg_ExpSolveArg( AST astExp, BOOL bSideEffect ){
	AST astLeftExp;
	AST astRightExp;
	AST astCmdList;
	AST astOperand;
	U4 kind;
	CG_RESULT result = { 0, 0 };
	CG_RESULT result_child = { 0, 0 };
	TRY;


	astLeftExp = stExpressionAccess.leftChild.get( astExp );
	result = cg_Expression( astLeftExp, bSideEffect );
	kind = stExpressionAccess.opKind.get( astLeftExp );
	if( kind != EXPR_ARG ){
		astOperand = CG_NewResultOperand( result.astEnd );
		astCmdList = CG_NewCmdListByKind( ASM_CMD_ASSIGNARG, astLeftExp );
		stCmdListAccess.rightOperand.set( astCmdList, astOperand );
		CG_CmdListSetType( astCmdList, stExpressionAccess.castedType.get( astLeftExp ) );
		result = CG_MergeCmdList( result, astCmdList );
	}
	astRightExp = stExpressionAccess.rightChild.get( astExp );
	result_child = cg_Expression( astRightExp, TRUE );
	result = CG_MergeResult( result, result_child );
	if( kind != EXPR_ARG ){
		astOperand = CG_NewResultOperand( result_child.astEnd );
		astCmdList = CG_NewCmdListByKind( ASM_CMD_ASSIGNARG, astRightExp );
		stCmdListAccess.rightOperand.set( astCmdList, astOperand );
		CG_CmdListSetType( astCmdList, stExpressionAccess.castedType.get( astRightExp ) );
		result = CG_MergeCmdList( result, astCmdList );
	}
	CATCH(result);
	return result;
}
static CG_RESULT cg_Expression( AST astExp, BOOL bSideEffect ){
	AST astConstant;
	AST astOperand;
	U4 kind;
	CG_RESULT result={0,0};

	TRY;
	astConstant = stExpressionAccess.constValue.get( astExp );
	if( astConstant ){
		if( bSideEffect ){
			result.astBegin = CG_NewCmdListByKind( ASM_CMD_GETOPERAND, astExp );
			astOperand = CG_NewConstantOperand( astConstant );
			stCmdListAccess.leftOperand.set( result.astBegin, astOperand );
			CG_CmdListSetType( result.astBegin, stExpressionAccess.type.get( astExp ) );
			result.astEnd = result.astBegin;
			return result;
		}else{
			return result;
		}
	}
	kind = stExpressionAccess.opKind.get( astExp );
	switch( kind ){
	case EXPR_IDENTIFIER:
	case EXPR_CONSTANT  :
	case EXPR_STRING:
		if( bSideEffect ){
			result = cg_ExpSolvePrimary( astExp, bSideEffect );
		}
		break;
	case EXPR_DECLARATION   :
		break;
	case EXPR_STATEMENT :
		result = cg_ExpSolveStatement( astExp, bSideEffect );
		break;
	case EXPR_PARENTHESE:
		result = cg_Expression( stExpressionAccess.leftChild.get( astExp ), bSideEffect );
		break;
	case EXPR_ARRAY :
		result = cg_ExpSolveArray( astExp, bSideEffect );
		break;
	case EXPR_FUNCTIONCALL  :
		result = cg_ExpSolveFuncCall( astExp, bSideEffect );
		break;
	case EXPR_MEMBER:
		result = cg_ExpSolveMember( astExp, bSideEffect );
		break;
	case EXPR_PTRMEMBER :
		result = cg_ExpSolvePtrMember( astExp, bSideEffect );
		break;
	case EXPR_POSTINC   :
	case EXPR_POSTDEC   :
		result = cg_ExpSolvePostIncDec( astExp, bSideEffect );
		break;
	case EXPR_COMPOUNDLITERALS:
		result = cg_ExpSolveCompoundLiterals( astExp, bSideEffect );
		break;
	case EXPR_PREINC   :
	case EXPR_PREDEC   :
		result = cg_ExpSolvePreIncDec( astExp, bSideEffect );
		break;
	case EXPR_ADDRESS:
		result = cg_ExpSolveAddress( astExp, bSideEffect );
		break;
	case EXPR_ASTERISK   :
		result = cg_ExpSolveAsterisk( astExp, bSideEffect );
		break;
	case EXPR_PLUS   :
	case EXPR_MINUS  :
	case EXPR_NEGATION   :
	case EXPR_BIT_NEGATION  :
		result = cg_ExpSolveSingleOp( astExp, bSideEffect );
		break;
	case EXPR_SIZEOF   :
		result = cg_ExpSolveSizeof( astExp, bSideEffect );
		break;
	case EXPR_CAST :
		result = cg_ExpSolveCast( astExp, bSideEffect );
		break;
	case EXPR_MUL  :
	case EXPR_DIV  :
	case EXPR_MOD  :
	case EXPR_ADD   :
	case EXPR_SUB   :
	case EXPR_LEFTSHIFT :
	case EXPR_RIGHTSHIFT:
	case EXPR_GREATER  :
	case EXPR_GREATEREQU   :
	case EXPR_LESS  :
	case EXPR_LESSEQU   :
	case EXPR_EQUAL :
	case EXPR_UNEQUAL   :
	case EXPR_BIT_AND   :
	case EXPR_BIT_EXOR  :
	case EXPR_BIT_INOR  :
		result = cg_ExpSolveBinary( astExp, bSideEffect );
		break;
	case EXPR_LOGIC_AND :
	case EXPR_LOGIC_OR  :
		result = cg_ExpSolveBinaryWithSqPoint( astExp, bSideEffect );
		break;
	case EXPR_CONDITION :
	case EXPR_COLON		   :
		result = cg_ExpSolveTernary( astExp, bSideEffect );
		break;
	case EXPR_ASSIGN:
	case EXPR_MUL_ASSIGN:
	case EXPR_DIV_ASSIGN:
	case EXPR_MOD_ASSIGN:
	case EXPR_ADD_ASSIGN:
	case EXPR_SUB_ASSIGN:
	case EXPR_LSHT_ASSIGN   :
	case EXPR_RSHT_ASSIGN   :
	case EXPR_BITAND_ASSIGN :
	case EXPR_BITEXOR_ASSIGN :
	case EXPR_BITINOR_ASSIGN :
		result = cg_ExpSolveAssign( astExp, bSideEffect );
		break;
	case EXPR_COMMA:
		result = cg_ExpSolveComma( astExp, bSideEffect );
		break;
	case EXPR_ARG  :
		result = cg_ExpSolveArg( astExp, bSideEffect );
		break;
	}
	CATCH(result);
	return result;
}

CG_RESULT CG_Expression( AST astExp, BOOL bSideEffect ){
	return cg_Expression( astExp, bSideEffect );
}
CG_RESULT CG_ExpPullPostIncDec( BOOL bClear ){
	return cg_ExpPullPostIncDec(bClear);
}
CG_RESULT CG_AddExpression( AST astPreCmdList, AST opKind, AST astRightExp ){
	AST astCmdList;
	AST astOperand;
	CG_RESULT result = { 0, 0 };

	if( astRightExp > 0 && astPreCmdList > 0 ){
		result = CG_Expression( astRightExp, TRUE );
		astOperand = CG_NewResultOperand( result.astEnd );
		astCmdList = CG_NewCmdListByKind( opKind, astRightExp );
		stCmdListAccess.rightOperand.set( astCmdList, astOperand );
		astOperand = CG_NewResultOperand( astPreCmdList );
		stCmdListAccess.leftOperand.set( astCmdList, astOperand );
		result = CG_MergeCmdList( result, astCmdList );
	}
	return result;
}
